/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.figures;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.draw2d.AbstractConnectionAnchor;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.PrecisionPoint;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.requests.CreateConnectionRequest;
import org.eclipse.gef.requests.ReconnectRequest;

public class SeDiAnchor extends AbstractConnectionAnchor {

    /**
     * A relatively unique tag or name for this anchor. By "relative" we mean that it is
     * unique within the owner figure. The tag can be used to reference an anchor within a
     * figure even though the anchor object is deleted (and later recreated as a new
     * object with the same tag). The model does not assume any particular "meaning" for
     * the tag, beyond that is something unique that it can use to identify a point. The
     * only entitity that may assign any particular meaning or structure to the tag is the
     * Figure that create it.
     */
    private final String tag;
    private int offSetX, offSetY;

    // A List of installed policies.
    private List<AnchorPolicy> policies;

    public SeDiAnchor(final IFigure owner, final String tag) {
        super(owner);
        this.tag = tag;
    }

    public Point getLocation(Point arg0) {
        Rectangle r = getOwner().getBounds();
        int x, y;
        y = r.y + offSetY;
        x = r.x + offSetX;
        Point p = new PrecisionPoint(x, y);
        getOwner().translateToAbsolute(p);
        return p;
    }

    public Point getReferencePoint() {
        return getLocation(null);
    }

    public void setRelativeLocation(final int x, final int y) {
        boolean moved = offSetX != x || offSetY != y;
        offSetX = x;
        offSetY = y;
        if (moved)
            fireAnchorMoved();
    }

    public int getOffsetX() {
        return offSetX;
    }

    public int getOffsetY() {
        return offSetY;
    }

    public String getTag() {
        return tag;
    }

    public void installPolicy(final AnchorPolicy policy) {
        if (policies == null)
            policies = new LinkedList<AnchorPolicy>();
        policies.add(policy);
    }

    public void removePolicy(final AnchorPolicy policy) {
        policies.remove(policy);
        if (policies.isEmpty())
            policies = null;
    }

    public boolean acceptConnectionCreate(final CreateConnectionRequest request) {
        if (policies != null) {
            for (AnchorPolicy p : policies)
                if (p.acceptConnectionCreate(this, request))
                    return true;
        }
        return false;
    }

    public boolean acceptConnectionComplete(final CreateConnectionRequest request) {
        if (policies != null) {
            for (AnchorPolicy p : policies)
                if (p.acceptConnectionComplete(this, request))
                    return true;
        }
        return false;
    }

    public boolean acceptReconnectSource(final ReconnectRequest request) {
        if (policies != null) {
            for (AnchorPolicy p : policies)
                if (p.acceptReconnectSource(this, request))
                    return true;
        }
        return false;
    }

    public boolean acceptReconnectTarget(final ReconnectRequest request) {
        if (policies != null) {
            for (AnchorPolicy p : policies)
                if (p.acceptReconnectTarget(this, request))
                    return true;
        }
        return false;
    }
}
